/* *****************************************************************************

  Copyright (C), 2001-2011, Huawei Tech. Co., Ltd.

 ******************************************************************************
  File Name     : hisec_cmd.h
  Version       : Initial Draft
  Created       : 2019/7/29
  Last Modified :
  Description   : secure commands between Driver and MPU/uCode
  Function List :
***************************************************************************** */

#ifndef HISEC_CMD_H
#define HISEC_CMD_H

#include "comm_defs.h"

#ifndef BIG_ENDIAN
#define BIG_ENDIAN 0x4321
#endif

#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 0x1234
#endif

/* CRYPT DRV to MPU Commands */
typedef enum hisec_mpu_cmd {
    HISEC_MPU_CMD_SET_IPSEC_OFFLOAD_MODE = 2,
    HISEC_MPU_CMD_GET_CRYPTO_STATS = 3,
    HISEC_MPU_CMD_GET_IPSEC_SAD = 4,
    HISEC_MPU_CMD_GET_IPSEC_SPD = 5,
    HISEC_MPU_CMD_GET_IPSEC_ITEM_CNT = 6,

    HISEC_MPU_CMD_MAX = 255
} hisec_mpu_cmd_type_e;

typedef enum hisec_npu_cmd_type {
    HISEC_NPU_CMD_SET_IPSEC_SA, /* IPsec SA child context 256B */
    HISEC_NPU_CMD_SET_IPSEC_SP, /* IPsec Secure Policy */
    HISEC_NPU_CMD_CALC_DH,

    HISEC_NPU_CMD_FLUSH_IPSEC_RES, /* IPsec flush resource */
    HISEC_NPU_CMD_INIT_SCQC,
    HISEC_NPU_CMD_DEINIT_SCQC,

    HISEC_NPU_CMD_MAX = 255
} hisec_npu_cmd_type_e;

typedef struct tag_hisec_cmd_hdr {
    union {
        struct {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            u32 rsvd0 : 16;
            u32 channel_id : 8;
            u32 cmd_type : 8; /* cmd type */
#else
            u32 cmd_type : 8;
            u32 channel_id : 8; /* logical concurrency channel */
            u32 rsvd0 : 16;
#endif
        } bs;
        u32 value;
    } dw0;

    u32 cmd_sn;
    u32 rsvd1[2];
} hisec_cmd_hdr_s;


typedef struct tag_hisec_cmd_init_scqc {
    hisec_cmd_hdr_s cmdhdr;

    u32 scqn;
    u32 rsvd;
    u32 scqc[10];
} hisec_cmd_init_scqc_s;

typedef struct tag_hisec_cmd_deinit_scqc {
    hisec_cmd_hdr_s cmdhdr;

    u32 scqn;
    u32 resvd[11];
} hisec_cmd_deinit_scqc_s;

typedef struct tag_hisec_cmd_flush_ipsec_res {
    hisec_cmd_hdr_s cmdhdr;

    u16 func_id;
    u16 rsvd0;
    u32 flush_flag;
    u32 rsvd1;
} hisec_cmd_flush_ipsec_res_s;

typedef struct tag_hisec_sa_enc_info {
    union {
        struct {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            u32 proto : 8;     /* tcp/udp */
            u32 direction : 8; /* out/in */
            u32 mode : 8;      /* 0 transport/ 1 tunnel */
            u32 flag : 8;      /* 1 -esn */
#else
            u32 flag : 8;
            u32 mode : 8;
            u32 direction : 8;
            u32 proto : 8;
#endif
        } bs;
        u32 value;
    } enc_dw0;

    union {
        struct {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            u32 replaywindow : 16; /* 32-64 */
            u32 alg_type : 8;      /* 0- aead 1-enc 2-auth 3-enc & auth */
            u32 alg_standard : 8;  /* 0 - aes, 3 - SM4 */
#else
            u32 alg_standard : 8;
            u32 alg_type : 8;
            u32 replaywindow : 16;
#endif
        } bs;
        u32 value;
    } enc_dw1;

    union {
        struct {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            u32 enc_type : 8;        /* hisec_crypto_alg_type */
            u32 auth_type : 8;       /* hisec_crypto_alg_type */
            u32 cipher_key_len : 16; /* in  bit */
#else
            u32 cipher_key_len : 16;
            u32 auth_type : 8;
            u32 enc_type : 8;
#endif
        } bs;
        u32 value;
    } enc_dw2;

    union {
        struct {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            u32 auth_key_len : 16;   /* in bit  */
            u32 auth_trunc_len : 16; /* in bit  */
#else
            u32 auth_trunc_len : 16;
            u32 auth_key_len : 16;
#endif
        } bs;
        u32 value;
    } enc_dw3;

    union {
        struct {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            u32 icv_mac_len : 16; /* in bit  */
            u32 rsvd1 : 16;
#else
            u32 rsvd1 : 16;
            u32 icv_mac_len : 16;

#endif
        } bs;
        u32 value;
    } enc_dw4;

    u32 salt; /* 32bit */

    u32 pad[2];

    u32 cipher_key[8]; /* 128bit 192bit 256bit	*/
    u32 auth_key[8];   /* 256bit */
} hisec_sa_enc_info_s;

typedef struct tag_hisec_sa_tuples {
    u32 daddr[4]; /* ipv4 in daddr[0] */
    u32 spi;

    union {
        struct {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            u32 ipsec_proto : 8;
            u32 iptype : 8; /* 0-ipv4 1-ipv6 */
            u32 rsvd : 16;
#else
            u32 rsvd : 16;
            u32 iptype : 8;
            u32 ipsec_proto : 8;
#endif
        } bs;
        u32 value;
    } tup_dw0;

    u32 pad[2];
} hisec_sa_tuples_s;

/* IPsec SA msg 160B */
typedef struct tag_hisec_cmd_set_ipsec_sa {
    hisec_cmd_hdr_s cmdhdr; /* 16B */

    hisec_sa_tuples_s tuples; /* 32B */

    union {
        struct {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            u32 opid : 8; /* 0-add 1-del 2-update 3-flush */
            u32 rsvd0 : 24;
#else
            u32 rsvd0 : 24;
            u32 opid : 8;
#endif
        } bs;
        u32 value;
    } sa_dw0;

    u32 scqn; /* used for scqe sa aging update msg notify */

    u32 pad[2];

    hisec_sa_enc_info_s enc_info;
} hisec_cmd_set_ipsec_sa_s;

typedef struct tag_hisec_sp_tuples {
    u32 saddr[4]; /* ipv4 in saddr[0] */
    u32 daddr[4]; /* ipv4 in daddr[0] */
    u32 sa_masklen;
    u32 da_masklen;

    union {
        struct {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            u32 dport : 16;
            u32 sport : 16;
#else
            u32 sport : 16;
            u32 dport : 16;
#endif
        } bs;
        u32 value;
    } tup_dw0;

    union {
        struct {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            u32 dport_mask : 16;
            u32 sport_mask : 16;
#else
            u32 sport_mask : 16;
            u32 dport_mask : 16;
#endif
        } bs;
        u32 value;
    } tup_dw1;

    union {
        struct {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            u32 ulp_proto : 8; /*  tcp/udp */
            u32 iptype : 8;    /* 0-ipv4 1-ipv6 */
            u32 rsvd0 : 16;
#else
            u16 rsvd0;
            u8 iptype;
            u8 ulp_proto;
#endif
        } bs;
        u32 value;
    } tup_dw2;

    u32 pad[3];
} hisec_sp_tuples_s;

/* IPsec SP msg 128B */
typedef struct tag_hisec_cmd_set_ipsec_sp {
    hisec_cmd_hdr_s cmdhdr;

    hisec_sp_tuples_s tuples;

    u32 spi;

    union {
        struct {
#if (BYTE_ORDER == LITTLE_ENDIAN)
            u32 ipsec_proto : 8; /* 50-esp 51-ah */
            u32 opid : 8;        /* 0-add 1-del 2-update */
            u32 action : 8; /* 0-bypass 1-encrypted */
            u32 rsvd0 : 8;
#else
            u32 rsvd0 : 8;
            u32 action : 8;
            u32 opid : 8;
            u32 ipsec_proto : 8;
#endif
        } bs;
        u32 value;
    } sp_dw0;

    u32 pad[10];
} hisec_cmd_set_ipsec_sp_s;

typedef struct tag_hisec_cmd_dh_param {
#if (BYTE_ORDER == LITTLE_ENDIAN)
    u16 generator;
    u8 dh_phase; /* 1-DH Phase1 2- DH Phase 2 */
    u8 dh_groupid;
#else
    u8 dh_groupid;
    u8 dh_phase; /* 1-DH Phase1 2- DH Phase 2 */
    u16 generator;
#endif

#if (BYTE_ORDER == LITTLE_ENDIAN)
    u16 privkey_len;
    u16 modp_len;
#else
    u16 modp_len;
    u16 privkey_len;
#endif

#if (BYTE_ORDER == LITTLE_ENDIAN)
    u16 rsvd0;
    u16 pubkey_len;
#else
    u16 pubkey_len;
    u16 rsvd0;
#endif

    u32 rsvd1[13];

    u32 modprime[128];    /* public prime number */
    u32 private_key[128]; /* private Xa */
    u32 public_key[128];  /* public Yb */
} hisec_cmd_dh_param_s;

typedef struct tag_hisec_cmd_calc_dh {
    hisec_cmd_hdr_s cmdhdr;

    /* writeback result PhyAddr */
    u32 buf_len;
    u32 buf_gpah;
    u32 buf_gpal;

    /* writeback result LogicalVirtualAddr */
    u32 buf_vah;
    u32 buf_val;

    /* detect memory tramp */
    u32 magic_h;
    u32 magic_l;

    u32 scqn;
    u32 rsvd[4];

    hisec_cmd_dh_param_s dh_param;
} hisec_cmd_calc_dh_s;

struct hisec_cmd_ipsec_offload_mode {
    struct comm_info_head msg_head;

    u16 func_id;
    u8 offload_mode; /* 0-disable 1-xfrm offload 2-ipsec full offload */
    u8 rsvd1[5];
};

struct hisec_crypto_stats {
    u64 cryrx_auth_err;
    u64 cryrx_tfc_pad_err;
    u64 cryrx_other_err;
    u64 crytx_bd_err;
    u64 crytx_len_err;
};

struct hisec_cmd_cryptodev_stats {
    struct comm_info_head msg_head;
    struct hisec_crypto_stats stats;
};

struct hisec_cmd_ipsec_item_cnt {
    struct comm_info_head msg_head;

    u32 sp_item_cnt;
    u32 sa_item_cnt;
    u16 func_id;
    u16 pad;
};

typedef union {
    struct {
        u32 tbl_index;
        u32 cnt;
        u32 total_cnt;
    } tbl_arg;
    u32 args[4];
} ipsec_sml_tbl_args;

#define IPSEC_SML_TBL_BUF_MAX (768)

struct hisec_cmd_sml_table {
    struct comm_info_head msg_head;
    u16 func_id;
    u32 tbl_type;
    ipsec_sml_tbl_args args;
    u8 tbl_buf[IPSEC_SML_TBL_BUF_MAX];
};

#endif /* HISEC_CMD_H */
